package mi.payment.utils.iso8583;


import android.text.TextUtils;

import java.io.UnsupportedEncodingException;
import java.util.HashMap;
import java.util.Locale;

import sunmi.sunmiui.utils.LogUtil;

/**
 * 解包
 *
 * @author lee on 2017/2/10.
 */
public class DecodePackage {

    public final static String TAG = "DecodePackage";

    public static HashMap<String, MsgField> unAssembly(byte[] body) {
        return unAssembly(body, FieldConfig.FieldTypeConfig128);
    }

    public synchronized static HashMap<String, MsgField> unAssembly(byte[] body, int[][] fieldConfig) {
        HashMap<String, MsgField> resMap = new HashMap<>();

        // 请求头长度15
        // Len[2] + tPDU[5] + Header[6] + Type[2]
        int head = 7 + FieldConfig.MESSAGE_HEADER_LENGTH;

        // 计算报文类型长度
        byte[] msgData = null;
        int typeLength = FieldConfig.FieldTypeConfig128[0][2];
        switch (FieldConfig.FieldTypeConfig128[0][3]) {
            case FieldConfig.SDK_8583_DATA_BCD:
                head += (typeLength + 1) / 2;
                msgData = new byte[(typeLength + 1) / 2];
                break;
            case FieldConfig.SDK_8583_DATA_ASC:
            case FieldConfig.SDK_8583_DATA_BIT:
                head += typeLength;
                msgData = new byte[typeLength];
                break;
            default:
                break;
        }
        // 取报文头
        byte[] headerData = new byte[FieldConfig.MESSAGE_HEADER_LENGTH];
        System.arraycopy(body, 7, headerData, 0, FieldConfig.MESSAGE_HEADER_LENGTH);
        MsgField headerFiled = new MsgField();
        headerFiled.setFieldPos(-1);
        headerFiled.setLengthType(fieldConfig[0][0]);
        headerFiled.setLengthTypeEncode(fieldConfig[0][1]);
        headerFiled.setDataType(fieldConfig[0][3]);
        headerFiled.setAlignType(fieldConfig[0][4]);
        headerFiled.setFillChar(fieldConfig[0][5]);
        headerFiled.setDataLength(fieldConfig[0][2]);
        headerFiled.setDataBytes(headerData);
        headerFiled.setDataStr(Utils.byte2HexStr(headerData));
        resMap.put("header", headerFiled);
        String header = Utils.byte2HexStr(headerData);
        LogUtil.e(TAG, "header：" + header);

        // 取消息类型
        System.arraycopy(body, 7 + FieldConfig.MESSAGE_HEADER_LENGTH, msgData, 0, msgData.length);
        String msgType = "";
        switch (FieldConfig.FieldTypeConfig128[0][3]) {
            case FieldConfig.SDK_8583_DATA_BCD:
            case FieldConfig.SDK_8583_DATA_BIT:
                msgType = Utils.byte2HexStr(msgData);
                break;
            case FieldConfig.SDK_8583_DATA_ASC:
                try {
                    msgType = new String(msgData, "ISO-8859-1");
                } catch (UnsupportedEncodingException e) {
                    e.printStackTrace();
                }
                break;
            default:
                break;
        }

        MsgField msgFiled = new MsgField();
        msgFiled.setFieldPos(0);
        msgFiled.setLengthType(fieldConfig[0][0]);
        msgFiled.setLengthTypeEncode(fieldConfig[0][1]);
        msgFiled.setDataType(fieldConfig[0][3]);
        msgFiled.setAlignType(fieldConfig[0][4]);
        msgFiled.setFillChar(fieldConfig[0][5]);
        msgFiled.setDataLength(fieldConfig[0][2]);
        msgFiled.setDataBytes(msgData);
        msgFiled.setDataStr(msgType);
        resMap.put("type", msgFiled);
        LogUtil.e(TAG, "消息类型：" + msgType);

        // 取得位图
        boolean[] boolBitmap;
        byte[] bitmap = new byte[8];
        System.arraycopy(body, head, bitmap, 0, 8);
        boolBitmap = Utils.getBinaryFromByte(bitmap);
        if (boolBitmap[1]) {
            // 如果第一位为1,则是可扩展位图,设为16字节长度.
            byte[] b = new byte[16];
            System.arraycopy(body, head, b, 0, 16);
            boolBitmap = Utils.getBinaryFromByte(b);
            head += 16;
        } else {
            head += 8;
        }

        int size = boolBitmap.length;

        // 请求头和位图的总长度
        int tmpLen = head;

        // 0 1 域不用
        for (int i = 2; i < size; i++) {
            if (boolBitmap[i]) {
                MsgField outField = new MsgField();
                outField.setFieldPos(i);
                outField.setLengthType(fieldConfig[i][0]);
                outField.setLengthTypeEncode(fieldConfig[i][1]);
                outField.setDataType(fieldConfig[i][3]);
                outField.setAlignType(fieldConfig[i][4]);
                outField.setFillChar(fieldConfig[i][5]);
                // len对变长是无用的。
                outField.setDataLength(fieldConfig[i][2]);

                byte[] nextData;

                // 取出变长部分的值
                if (outField.getLengthType() > 0) {
                    // 取出长度的字节数组
                    int varLen = (outField.getLengthType() + 1) / 2;
                    byte[] varValue = new byte[varLen];
                    System.arraycopy(body, tmpLen, varValue, 0, varValue.length);
                    // 数据长度的长度
                    tmpLen += varLen;

                    // 变长的数据的字节数
                    int datLen;
                    int bcdLength = Utils.bcdToint(varValue);
                    // 判断数据类型(binary类型数据没有处理)
                    if (outField.getDataType() == FieldConfig.SDK_8583_DATA_BCD) {
                        datLen = (bcdLength / 2) + (bcdLength % 2);
                        outField.setDataLength(bcdLength); // 填充变长的长度
                    } else if (outField.getDataType() == FieldConfig.SDK_8583_DATA_BIT) {
                        datLen = bcdLength;
                        outField.setDataLength(2 * bcdLength); // 填充变长的长度
                    } else {
                        //asc
                        datLen = bcdLength;
                        outField.setDataLength(bcdLength); // 填充变长的长度
                    }

                    // 取出变长部分后带的值。
                    nextData = new byte[datLen];
                    System.arraycopy(body, tmpLen, nextData, 0, datLen);

                    // 数据的长度
                    tmpLen += datLen;

                } else {
                    // 定长的数据长度
                    int datLen;
                    // 判断数据类型(binary类型数据没有处理)
                    if (outField.getDataType() == FieldConfig.SDK_8583_DATA_BCD) {
                        datLen = (outField.getDataLength() / 2) + (outField.getDataLength() % 2);
                    } else if (outField.getDataType() == FieldConfig.SDK_8583_DATA_ASC) {
                        datLen = outField.getDataLength();
                    } else {
                        datLen = outField.getDataLength();
                    }
                    nextData = new byte[datLen];
                    System.arraycopy(body, tmpLen, nextData, 0, nextData.length);
                    tmpLen += nextData.length;
                }

                // 填充数据
                if (outField.getDataType() == FieldConfig.SDK_8583_DATA_ASC) {
                    String s = null;
                    try {
                        s = new String(nextData, "gbk");
                    } catch (UnsupportedEncodingException e) {
                        e.printStackTrace();
                    }
                    if (!TextUtils.isEmpty(s) && Utils.isMessyCode(s)) {
                        LogUtil.e(TAG, "field pos:" + outField.getFieldPos() + " = " + Utils.byte2HexStr(nextData));
                    } else {
                        LogUtil.e(TAG, "field pos:" + outField.getFieldPos() + " = " + s);
                    }
                    // 判断是不是GBK编码 即是否乱码
                    outField.setDataStr(new String(nextData));
                } else if (outField.getDataType() == FieldConfig.SDK_8583_DATA_BIT) {
                    LogUtil.e(TAG, "field pos:" + outField.getFieldPos() + " = " + Utils.byte2HexStr(nextData));
                    outField.setDataStr(Utils.byte2HexStr(nextData));
                } else if (outField.getDataType() == FieldConfig.SDK_8583_DATA_BCD) {
                    LogUtil.e(TAG, "field pos:" + outField.getFieldPos() + " = " + Utils.Bcd2String(nextData));
                    outField.setDataStr(Utils.Bcd2String(nextData));
                }

                outField.setDataBytes(nextData);
                resMap.put("F" + String.format(Locale.getDefault(), "%03d", i), outField);
            }
        }

        return resMap;
    }

    public synchronized static HashMap<String, MsgField> unAssembly(byte[] body, int[][] msgFront, int[][] fieldConfig) {
        int msgFrontLen = msgFront.length;
        int index = 0;
        for (int i = 0; i < msgFrontLen; i++) {
            byte[] value = new byte[0];
            switch (msgFront[i][1]) {
                case FieldConfig.SDK_8583_DATA_ASC:
                    value = new byte[msgFront[i][0]];
                    System.arraycopy(body, index, value, 0, value.length);
                    try {
                        LogUtil.e(TAG, "msgFront:" + i + ":" + new String(value, "ISO-8859-1"));
                    } catch (UnsupportedEncodingException e) {
                        e.printStackTrace();
                    }
                    break;
                case FieldConfig.SDK_8583_DATA_BCD:
                    value = new byte[(msgFront[i][0] + 1) / 2];
                    System.arraycopy(body, index, value, 0, value.length);
                    LogUtil.e(TAG, "msgFront:" + i + ":" + Utils.byte2HexStr(value));
                    break;
                case FieldConfig.SDK_8583_DATA_BIT:
                    value = new byte[msgFront[i][0]];
                    System.arraycopy(body, index, value, 0, value.length);
                    String hexStr = Utils.byte2HexStr(value);
                    if (value.length < 5) {
                        hexStr += "：10进制:" + Utils.bytes2Int(value);
                    }
                    LogUtil.e(TAG, "msgFront:" + i + ":" + hexStr);
                    break;
                default:
                    break;
            }
            index += value.length;
        }
        HashMap<String, MsgField> resMap = new HashMap<>();

        // 请求头长度15
        // Len[2] + tPDU[5] + Header[6] + Type[2]
        // int head = 7 + FieldConfig.MESSAGE_HEADER_LENGTH;

        int tLen = 0;
        // 计算报文类型长度
        int typeLength = fieldConfig[0][2];
        switch (fieldConfig[0][3]) {
            case FieldConfig.SDK_8583_DATA_BCD:
                tLen = (typeLength + 1) / 2;
                break;
            case FieldConfig.SDK_8583_DATA_ASC:
            case FieldConfig.SDK_8583_DATA_BIT:
                tLen = typeLength;
                break;
            default:
                break;
        }
        int bitIndex = index + tLen;
        byte[] bitBytes = new byte[fieldConfig[1][2]];
        System.arraycopy(body, bitIndex, bitBytes, 0, bitBytes.length);
        boolean[] boolBitmap = Utils.getBinaryFromByte(bitBytes);
        boolBitmap[0] = true;
        boolBitmap[1] = true;

        int size = boolBitmap.length;

        // 0 1 域不用
        for (int i = 0; i < size; i++) {
            if (boolBitmap[i]) {
                MsgField outField = new MsgField();
                outField.setFieldPos(i);
                outField.setLengthType(fieldConfig[i][0]);
                outField.setLengthTypeEncode(fieldConfig[i][1]);
                outField.setDataType(fieldConfig[i][3]);
                outField.setAlignType(fieldConfig[i][4]);
                outField.setFillChar(fieldConfig[i][5]);
                // len对变长是无用的。
                outField.setDataLength(fieldConfig[i][2]);

                byte[] nextData;

                // 取出变长部分的值
                if (outField.getLengthType() > 0) {
                    // 取出长度的字节数组
                    int varLen = (outField.getLengthType() + 1) / 2;
                    byte[] varValue = new byte[varLen];
                    System.arraycopy(body, index, varValue, 0, varValue.length);
                    // 数据长度的长度
                    index += varLen;

                    // 变长的数据的字节数
                    int datLen;
                    int bcdLength = Utils.bcdToint(varValue);
                    // 判断数据类型(binary类型数据没有处理)
                    if (outField.getDataType() == FieldConfig.SDK_8583_DATA_BCD) {
                        datLen = (bcdLength / 2) + (bcdLength % 2);
                        outField.setDataLength(bcdLength); // 填充变长的长度
                    } else if (outField.getDataType() == FieldConfig.SDK_8583_DATA_BIT) {
                        datLen = bcdLength;
                        outField.setDataLength(2 * bcdLength); // 填充变长的长度
                    } else {
                        //asc
                        datLen = bcdLength;
                        outField.setDataLength(bcdLength); // 填充变长的长度
                    }

                    // 取出变长部分后带的值。
                    nextData = new byte[datLen];
                    System.arraycopy(body, index, nextData, 0, datLen);

                    // 数据的长度
                    index += datLen;

                } else {
                    // 定长的数据长度
                    int datLen;
                    // 判断数据类型(binary类型数据没有处理)
                    if (outField.getDataType() == FieldConfig.SDK_8583_DATA_BCD) {
                        datLen = (outField.getDataLength() / 2) + (outField.getDataLength() % 2);
                    } else if (outField.getDataType() == FieldConfig.SDK_8583_DATA_ASC) {
                        datLen = outField.getDataLength();
                    } else {
                        datLen = outField.getDataLength();
                    }
                    nextData = new byte[datLen];
                    System.arraycopy(body, index, nextData, 0, nextData.length);
                    index += nextData.length;
                }

                // 填充数据
                if (outField.getDataType() == FieldConfig.SDK_8583_DATA_ASC) {
                    try {
                        String s = new String(nextData, "gbk");
                        if (!Utils.isMessyCode(s)) {
                            LogUtil.e(TAG, "field pos:" + outField.getFieldPos() + " = " + s);
                        } else {
                            LogUtil.e(TAG, "field pos:" + outField.getFieldPos() + " = " + Utils.byte2HexStr(nextData));
                        }
                    } catch (UnsupportedEncodingException e) {
                        e.printStackTrace();
                    }
                    outField.setDataStr(new String(nextData));
                } else if (outField.getDataType() == FieldConfig.SDK_8583_DATA_BIT) {
                    LogUtil.e(TAG, "field pos:" + outField.getFieldPos() + " = " + Utils.byte2HexStr(nextData));
                    outField.setDataStr(Utils.byte2HexStr(nextData));
                } else if (outField.getDataType() == FieldConfig.SDK_8583_DATA_BCD) {
                    LogUtil.e(TAG, "field pos:" + outField.getFieldPos() + " = " + Utils.Bcd2String(nextData));
                    outField.setDataStr(Utils.Bcd2String(nextData));
                }

                outField.setDataBytes(nextData);
                resMap.put("F" + String.format(Locale.getDefault(), "%03d", i), outField);
            }
        }

        return resMap;
    }


}
